﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq.Mapping;
using System.Configuration;

namespace GoodStuff.Diagnostics
{
    internal class ExceptionHandlerSql : IExceptionHandler
    {        
        private string _connectionString;
        private ExceptionHandlerSqlConfiguration _config;

        public ExceptionHandlerSql(ExceptionHandlerSqlConfiguration config)
        {
            if (string.IsNullOrEmpty(config.ConnectionName))
            {
                throw new ConfigurationErrorsException(string.Format("ExceptionSql-Module; a required connectionName value not configured. "));
            }

            _connectionString = ConfigurationHelper.GetConnectionString(config.ConnectionName);
            if (string.IsNullOrEmpty(_connectionString))
            {
                throw new ConfigurationErrorsException(string.Format("ExceptionSql-Module; connectionName '" + _connectionString +"' not found. "));
            }

            //save config
            _config = config;
        }

        public void HandleException(Exception ee, System.Web.HttpRequest request)
        {
            using (System.Data.Linq.DataContext context = new System.Data.Linq.DataContext(_connectionString))
            {
                //fill and insert the record.
                var table = context.GetTable<LogEntry>();

                table.InsertOnSubmit(new LogEntry()
                {
                    ID = Guid.NewGuid(),
                    Application = Maximize(request.ApplicationPath, 50),    //nvarchar(50)
                    Date = DateTime.Now,
                    Message = ee.Message ?? string.Empty,          //ntext
                    Module = Maximize(ee.Source, 250),             //nvarchar(250)
                    QueryString = Maximize(request.QueryString.ToString(), 150),   //nvarchar(150)
                    RemoteIP = Maximize(request.UserHostAddress, 20),          //nvarchar(20)
                    Severity = (int)0,
                    StackTrace = ee.ToString("\n"),    //ntext, Extension
                    HostHeader = Maximize(request.Url.Host, 150),     //nvarchar(150)
                    Url = Maximize(request.Url.AbsolutePath, 150)                    //nvarchar(150)
                });

                context.SubmitChanges();
            }
        }

        private string Maximize(string input, int maxLength)
        {
            input = input ?? string.Empty;
            if (input.Length > maxLength)
            {
                return input.Substring(0, maxLength);
            }
            return input;
        }

        /* internal and dynamic LogEntry class */

        [Table(Name = "dbo.LogEntries")]
        public partial class LogEntry
        {
            [Column(DbType = "UniqueIdentifier NOT NULL", IsPrimaryKey = true)]
            public System.Guid ID { get; set; }

            [Column(DbType = "DateTime NOT NULL")]
            public System.DateTime Date { get; set; }

            [Column(DbType = "Int NOT NULL")]
            public int Severity { get; set; }

            [Column( DbType = "NVarChar(50) NOT NULL", CanBeNull = false)]
            public string Module { get; set; }

            [Column(DbType = "NText NOT NULL", CanBeNull = false, UpdateCheck = UpdateCheck.Never)]
            public string Message { get; set; }

            [Column(DbType = "NVarChar(20) NOT NULL", CanBeNull = false)]
            public string RemoteIP { get; set; }

            [Column(DbType = "NVarChar(150) NOT NULL", CanBeNull = false)]
            public string HostHeader { get; set; }

            [Column(DbType = "NVarChar(150) NOT NULL", CanBeNull = false)]
            public string Url { get; set; }

            [Column(DbType = "NVarChar(150) NOT NULL", CanBeNull = false)]
            public string QueryString { get; set; }

            [Column(DbType = "NText NOT NULL", CanBeNull = false, UpdateCheck = UpdateCheck.Never)]
            public string StackTrace { get; set; }

            [Column(DbType = "NVarChar(50) NOT NULL", CanBeNull = false)]
            public string Application { get; set; }
        }


        public IList<ExceptionHandlerExclude> Excludes
        {
            get { return _config.Excludes; }
        }

    }
}
